package utils

import (
	"encoding/json"
	"fmt"
	"net/url"
	"reflect"
	"strconv"
	"strings"
	"time"
)

type HourlyTimeModel struct {
	Date  string `json:"date"`  // 时间
	Value string `json:"value"` // 值
}

func DisassembleString(str string, substr string) string {
	var remainder string
	index := strings.Index(str, substr)
	if index != -1 {
		// 如果找到了子字符串，则获取它之后的部分（包括index之后的字符）
		remainder = str[index+len(substr):]
	} else {
		return ""
	}
	return remainder
}

func DisassembleInt(str string, substr string) int {
	index := strings.Index(str, substr)
	if index != -1 {
		// 如果找到了子字符串，返回子字符串之后的索引（即子字符串最后一个字符后的索引）
		return index + len(substr)
	}
	// 如果没有找到子字符串，返回-1
	return -1
}

func NoLineTime(data string) int {
	t, _ := time.Parse("2006-01-02 15:04:05", data)
	formatted := t.Format("20060102")
	dateInt, _ := strconv.Atoi(formatted)
	return dateInt
}

func LineTime(data string) string {
	t, _ := time.Parse("2006-01-02 15:04:05", data)
	formatted := t.Format("2006-01-02")
	return formatted
}

func StrUrl(baseURL string, argument interface{}) string {
	values := url.Values{}

	// 反射获取JsLoginRequest的字段
	v := reflect.ValueOf(argument)
	if v.Kind() == reflect.Ptr {
		v = v.Elem()
	}

	// 遍历字段
	for i := 0; i < v.NumField(); i++ {
		typeField := v.Type().Field(i)
		valueField := v.Field(i)

		// 检查字段是否非空
		if valueField.IsValid() && !valueField.IsZero() {
			// 获取JSON标签中定义的字段名
			jsonName := typeField.Tag.Get("json")
			if jsonName != "" {
				// 如果有逗号分隔的备选项，只取第一个
				if parts := strings.Split(jsonName, ","); len(parts) > 0 {
					jsonName = parts[0]
				}
				switch valueField.Kind() {
				case reflect.String:
					// 将字段值转换为字符串并添加到values中
					values.Add(jsonName, valueField.String())
				case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
					// 将字段值转换为字符串并添加到values中
					values.Add(jsonName, fmt.Sprint(valueField.Int()))
				// ... 你可以根据需要添加其他类型的处理
				default:
					// 忽略不支持的类型
					continue
				}

			}
		}
	}

	// 将values转换为查询字符串并附加到URL
	parsedURL, err := url.Parse(baseURL)
	if err != nil {
		return err.Error()
	}
	parsedURL.RawQuery = values.Encode()

	// 返回完整的URL
	return parsedURL.String()
}

// DateDiff - 计算两个日期之间的差值
func DateDiff(start_time string, end_time string, diffType string) int {
	dateEnd, _ := time.Parse("2006-01-02", end_time)
	dateStart, _ := time.Parse("2006-01-02", start_time)
	timeDiff := dateEnd.Sub(dateStart)
	if diffType == "hour" {
		hours := int(timeDiff.Hours())
		return hours
	}

	days := int(timeDiff.Hours() / 24)
	return days
}

// InterfaceToString - 对象序列化为字符串
func InterfaceToString(obj interface{}) string {
	jsonByte, _ := json.MarshalIndent(obj, "", "\t")
	return string(jsonByte)
}

// DateToUnix - 日期to时间戳
func DateToUnix(date string, layout string) int64 {
	if date == "" {
		return 0
	}
	if layout == "" {
		layout = time.DateOnly
	}
	t, _ := time.Parse(layout, date)
	return t.Unix()
}

// UnixToDate - 时间戳to日期
func UnixToDate(date int64, layout string) string {
	if date == 0 {
		return ""
	}
	if layout == "" {
		layout = time.DateOnly
	}
	t := time.Unix(date, 0)
	return t.Format(layout)
}

// DateFormat - 日期格式化
func DateFormat(date string, layout string, format string) string {
	if date == "" {
		return date
	}
	if layout == "" {
		layout = time.DateOnly
	}
	t, _ := time.Parse(layout, date)
	return t.Format(format)
}

// IntToTime - int转时间
func IntToTime(i int) string {
	if i < 10 {
		return "0" + strconv.Itoa(i)
	}
	return strconv.Itoa(i)
}

// GetDatesInRange 返回给定时间范围内的所有日期
func GetDatesInRange(startDateStr, endDateStr string) []*HourlyTimeModel {
	// 解析开始和结束日期
	startDate, err := time.Parse("2006-01-02 15:04:05", startDateStr)
	if err != nil {
		fmt.Printf("Error parsing start date: %v\n", err)
		return nil
	}
	endDate, err := time.Parse("2006-01-02 15:04:05", endDateStr)
	if err != nil {
		fmt.Printf("Error parsing end date: %v\n", err)
		return nil
	}

	// 如果结束日期小于开始日期，则交换它们
	if endDate.Before(startDate) {
		startDate, endDate = endDate, startDate
	}

	// 创建一个切片来保存日期
	hourlyTimesModels := make([]*HourlyTimeModel, 0)

	// 当前日期设置为起始日期
	currentDate := startDate

	// 循环添加日期到切片中，直到达到结束日期（不包含）
	for !currentDate.After(endDate) {
		// 创建HourlyTimeModel实例并添加到切片中
		hourlyTimesModels = append(hourlyTimesModels, &HourlyTimeModel{
			Date:  currentDate.Format("2006-01-02"),
			Value: "-", // 这里可以根据需要设置其他值
		})
		currentDate = currentDate.AddDate(0, 0, 1) // 将当前日期加1天
	}

	return hourlyTimesModels
}

// GenerateHourlyTimes - 返回给定时间范围内所有小时的时间字符串
func GenerateHourlyTimes(date string) []*HourlyTimeModel {
	// 解析日期
	layout := "2006-01-02"
	t, err := time.Parse(layout, date)
	if err != nil {
		panic(err)
	}

	// 设置时间为当天的起始时间（即 00:00:00）
	t = t.Truncate(24 * time.Hour)

	// 创建一个切片来存储整点时间模型
	hourlyTimesModels := make([]*HourlyTimeModel, 24)

	// 遍历小时
	for i := 0; i < 24; i++ {
		// 设置当前小时的时间
		currentHour := t.Add(time.Duration(i) * time.Hour)

		// 格式化时间字符串为 "HH:MM"
		hourlyTimeStr := currentHour.Format("15:04")

		// 创建HourlyTimeModel实例并赋值
		hourlyTimesModels[i] = &HourlyTimeModel{
			Date:  hourlyTimeStr,
			Value: "-",
		}
	}

	return hourlyTimesModels
}

// DaysBetween 计算两个时间之间相差的天数
func DaysBetween(startTime, endTime time.Time) int {
	// 计算两个时间的差值
	duration := endTime.Sub(startTime)

	// 将差值转换为天数
	// 注意：这里假设每天有24小时，不考虑闰秒和其他微妙的时间变化
	days := int(duration.Hours() / 24)

	// 如果需要更精确的计算（考虑时区变化等），则可能需要更复杂的逻辑
	return days
}

// GetHoursSpecific 返回特定时间小时整
func GetHoursSpecific(startDateStr string) string {
	// 定义时间字符串和格式
	const layout = "2006-01-02 15:04:05"

	// 解析时间字符串
	t, err := time.Parse(layout, startDateStr)
	if err != nil {
		fmt.Println("解析时间错误:", err)
		return ""
	}

	// 获取整点小时
	return fmt.Sprintf("%02d:00", t.Hour())
}

// GetCurrentHour12hFormat 返回当前小时，格式为12小时制（如 "12:00"）
func GetCurrentHour12hFormat() string {
	// 获取当前时间
	now := time.Now()

	// 格式化时间，只显示小时和分钟（分钟固定为00）
	// "%02d" 表示小时数，至少两位，不足补0
	// ":00" 表示分钟数，固定为00
	return fmt.Sprintf("%02d:00", now.Hour())
}

// GetCurrentDate 返回当前日期的字符串表示，格式为"2024-06-13"
func GetCurrentDate() string {
	// 获取当前时间
	now := time.Now()

	// 格式化时间，只显示年-月-日
	// "2006-01-02" 是Go中时间格式化的参考时间，分别代表年-月-日
	return now.Format("2006-01-02")
}

// FormatDateWithoutSeparator 接收一个日期时间字符串，并返回没有分隔符的日期时间字符串
func FormatDateWithoutSeparator(dateTimeStr string) string {
	// 使用Go的参考时间格式来解析字符串
	t, _ := time.Parse("2006-01-02 15:04:05", dateTimeStr)

	// 使用没有分隔符的格式来格式化时间
	noSeparatorStr := t.Format("200601021504")

	return noSeparatorStr
}

// FormatDateSeparator 接收一个日期字符串，并返回没有分隔符的日期时间字符串
func FormatDateSeparator(dateTimeStr string) string {
	// 使用Go的参考时间格式来解析字符串
	t, _ := time.Parse("2006-01-02", dateTimeStr)

	// 使用没有分隔符的格式来格式化时间
	noSeparatorStr := t.Format("20060102")

	return noSeparatorStr
}

// Add365Days 方法给指定时间加上60年
func Add365Days(t time.Time) time.Time {
	return t.AddDate(60, 0, 0) // 使用AddDate方法加上1年0月0天
}

// SubtractOneDay 从给定的时间中减去一天
func SubtractOneDay(t time.Time) time.Time {
	return t.Add(-24 * time.Hour)
}

// ExtractAfterDash 从包含"-"的字符串中提取"-"后面的部分
func ExtractAfterDash(s string) (string, error) {
	parts := strings.Split(s, "-")
	if len(parts) < 2 {
		return "", fmt.Errorf("no '-' found in string: %s", s)
	}
	return parts[1], nil
}
